
/*
 * (a)  (C) 1990 by Adobe Systems Incorporated. All rights reserved.
 *
 * (b)  If this Sample Code is distributed as part of the Display PostScript
 *	System Software Development Kit from Adobe Systems Incorporated,
 *	then this copy is designated as Development Software and its use is
 *	subject to the terms of the License Agreement attached to such Kit.
 *
 * (c)  If this Sample Code is distributed independently, then the following
 *	terms apply:
 *
 * (d)  This file may be freely copied and redistributed as long as:
 *	1) Parts (a), (d), (e) and (f) continue to be included in the file,
 *	2) If the file has been modified in any way, a notice of such
 *      modification is conspicuously indicated.
 *
 * (e)  PostScript, Display PostScript, and Adobe are registered trademarks of
 *	Adobe Systems Incorporated.
 * 
 * (f) THE INFORMATION BELOW IS FURNISHED AS IS, IS SUBJECT TO
 *	CHANGE WITHOUT NOTICE, AND SHOULD NOT BE CONSTRUED
 *	AS A COMMITMENT BY ADOBE SYSTEMS INCORPORATED.
 *	ADOBE SYSTEMS INCORPORATED ASSUMES NO RESPONSIBILITY
 *	OR LIABILITY FOR ANY ERRORS OR INACCURACIES, MAKES NO
 *	WARRANTY OF ANY KIND (EXPRESS, IMPLIED OR STATUTORY)
 *	WITH RESPECT TO THIS INFORMATION, AND EXPRESSLY
 *	DISCLAIMS ANY AND ALL WARRANTIES OF MERCHANTABILITY, 
 *	FITNESS FOR PARTICULAR PURPOSES AND NONINFRINGEMENT
 *	OF THIRD PARTY RIGHTS.
 */

/*
 *	DrawingView.m
 *
 *	This view represents the page that the image is drawn onto. It is
 *	a subview of the DocView. The DocView is the document view of
 *	the ClipView. This view's real size grows with the scale but the
 *	bounds always stays the same.
 *
 *	Version:	2.0
 *	Author:	Ken Fromm
 *	History:
 *			03-07-91		Added this comment.
 */

#import "DrawingView.h"
#import "DocView.h"
#import "PatternApp.h"
#import "Pattern.h"
#import "PSWDrawingWraps.h"
#import "PSWpatterns.h"

#import <appkit/Button.h>
#import <appkit/Cell.h>
#import <appkit/Font.h>
#import <appkit/Matrix.h>
#import <appkit/Panel.h>
#import <appkit/nextstd.h>

#import <objc/List.h>
#import <dpsclient/dpsclient.h>
#import <dpsclient/wraps.h>

static NXRect			fillRect = {120, 250, 300, 260};

@implementation DrawingView

- initPatterns
{
	float		matrix[6];

	patterns = [[List  alloc]  initCount:16];

	[self  lockFocus];
	[patterns  addObject:[[Pattern  newPattern:"CircleStar"  size:0.72]
				definePatternRows:1 andCols:1]];
	[patterns  addObject:[[Pattern  newPattern:"CircleStar"  size:0.72]
				definePatternRows:2 andCols:2]];
	[patterns  addObject:[[Pattern  newPattern:"CircleStar"  size:0.72]
				definePatternRows:3 andCols:3]];
	[patterns  addObject:[[Pattern  newPattern:"CircleStar"  size:0.72]
				definePatternRows:4 andCols:4]];

	/*	The color is set here because the image is made at this time
	*	and we want it to be the same color as when used.
	*/
	PSsetgray(NX_LTGRAY);
	[patterns  addObject:[[Pattern  newPattern:"Octagon"  size:6]
				definePatternRows:1 andCols:1]];
	[patterns  addObject:[[Pattern  newPattern:"Octagon"  size:6]
				definePatternRows:2 andCols:2]];
	[patterns  addObject:[[Pattern  newPattern:"Octagon"  size:6]
				definePatternRows:3 andCols:3]];
	[patterns  addObject:[[Pattern  newPattern:"Octagon"  size:6] 
				definePatternRows:4 andCols:4]];

	[patterns  addObject:[[Pattern  newPattern:"Brick"  size:24]
				definePatternRows:1 andCols:1]];
	[patterns  addObject:[[Pattern  newPattern:"Brick"  size:24]
				definePatternRows:2 andCols:2]];
	[patterns  addObject:[[Pattern  newPattern:"Brick"  size:24]
				definePatternRows:3 andCols:3]];
	[patterns  addObject:[[Pattern  newPattern:"Brick"  size:24]
				definePatternRows:4 andCols:4]];

	matrix[0] = 2.59808; matrix[1] = 1.5; matrix[3] = -3.0; matrix[2] = matrix[4] = matrix[5] = 0.0;
	[patterns  addObject:[[Pattern  newPattern:"Weave"  size:3  matrix:matrix]
				definePatternRows:1 andCols:1]];
	[patterns  addObject:[[Pattern  newPattern:"Weave"  size:3  matrix:matrix]
				definePatternRows:2 andCols:2]];
	[patterns  addObject:[[Pattern  newPattern:"Weave"  size:3  matrix:matrix]
				definePatternRows:3 andCols:3]];
	[patterns  addObject:[[Pattern  newPattern:"Weave"  size:3  matrix:matrix]
				definePatternRows:4 andCols:4]];
	[self  unlockFocus];

	font = [Font  newFont:"Times-Roman"  size:FONTSIZE  matrix:NX_IDENTITYMATRIX];
	pattern = [patterns  objectAt:1];
	[self  showPattern:self];

	return self;
}

/*
*	This method changes the title of the menu cell according to the
*	value of the trace variable.
*/
- trace:sender
{
	if (trace == NO)
		[[sender selectedCell] setTitle:"Trace On"];
	else
		[[sender selectedCell] setTitle:"Trace Off"];

	trace = !trace;
	
	return self;
}

- images:sender
{
	id			image;

	int			i, count;

	NXCoord		maxheight;

	NXPoint		position;

	NXRect		rect;

	SEL			aSelector;

	if (images == NO)
	{
		[[sender selectedCell] setTitle:"Hide Images"];
		aSelector = @selector(orderFront:);
	}
	else
	{
		[[sender selectedCell] setTitle:"Show Images"];
		aSelector = @selector(orderOut:);
	}
	images = !images;

	count = [patterns  count];
	if (!imagesseen)
	{
		maxheight = 0.0;
		position.x = position.y = 0.0;
		for (i = 0; i < count; i++)
		{
			if (i % 8 == 0)
			{
				position.x = 2.0;
				position.y += maxheight + 5;
				maxheight = 0;
			}
			image = [[patterns  objectAt:i]  image];
			[image  moveTo:position.x  :position.y];
			[image  setFloatingPanel:YES];

			[image  getFrame:&rect];
			position.x += rect.size.width + 5;
			maxheight = MAX(maxheight, rect.size.height);
		}
	
		imagesseen = YES;
	}
	
	for (i = 0; i < count; i++)
		[[[patterns  objectAt:i]  image]  perform:aSelector  with:self];

	return self;
}

- pattern:sender
{
	int			tag, num;

	tag = [[NXApp  patternMatrix]  selectedTag];
	num = [[NXApp  countMatrix]  selectedTag];
	pattern = [patterns  objectAt:((tag * NUM_PATTERNS) + num)];
	[self  showPattern:self];

	[self  draw:self];

	return self;
}

- draw:sender
{
	NXRect	visRect;

	eraseFields = NO;

	[self  resetFields:self];
	[self  getVisibleRect:&visRect];
	[self  display:&visRect :1];

	[self  displayFields:self];

	return self;
}

- showPattern:sender
{
	id			box;

	NXPoint		pt;

	NXRect		boxRect;

	/*
	*	Composite the pattern into the options panel.
	*/
	box = [NXApp  patternBox];
	[box  getBounds:&boxRect];
	pt.x = (boxRect.origin.x + boxRect.size.width/2.0);
	pt.y = (boxRect.origin.y + boxRect.size.height/2.0);

	[box  lockFocus]; 
		[box  drawSelf:&boxRect  :1];
		[pattern  compositeTo:pt.x  :pt.y];
	[box  unlockFocus];
	[[box  window]  flushWindow];

	return self;
}

- eraseFields:sender
{
	id		matrixId;

	int		i;

	matrixId = [NXApp  timingMatrix];
	for (i= 0; i < [matrixId cellCount]; i++)
		[[matrixId cellAt:i :0] setStringValue:""];

	eraseFields = NO;

	return self;
}

- resetFields:sender
{
	/* Prepare for next time around. */
	timing.draws = timing.time = 0;

	return self;
}

- displayFields:sender
{
	 if (timing.draws)
		[[[NXApp timingMatrix] cellAt:0 :0]  setIntValue:rint(timing.time/timing.draws)];

	[self  resetFields:self];
	eraseFields = YES;

	return self;
}

/*
*	If the docview is zooming, then scale the drawing view.
*/
- mouseDown:(NXEvent *)event
{
	NXPoint		p;
	
 	p = event->location; 
	if ([superview  isZooming])
		return [nextResponder  scaleDrawViewToPoint:&p];

	return self;
}

- showGraphics:(NXRect *)r
{
	NXRect		strokeRect, testRect;

	/*
	*	For uncolored the pattern color should be set before setting it.
	*/
	PSsetgray(NX_LTGRAY);

	/*
	*	Sets the pattern. (Places the pattern dictionary on
	*	the dictionary stack.)
	*/
	[pattern set];

	if ([[[NXApp graphicsMatrix]  findCellWithTag:STROKE]  state])
	{
		strokeRect = fillRect;
		NXInsetRect(&strokeRect, -30, -30);
		testRect = strokeRect;
		NXInsetRect(&testRect, -STROKEWIDTH/2.0, -STROKEWIDTH/2.0);
		if (NXIntersectsRect(r, &testRect))
		{	
			PSsetlinewidth(STROKEWIDTH);
			PSrectstroke(NX_X(&strokeRect), NX_Y(&strokeRect),
					NX_WIDTH(&strokeRect), NX_HEIGHT(&strokeRect));
		}
	}

	if ([[[NXApp graphicsMatrix]  findCellWithTag:FILL]  state])
	{
		if (NXIntersectsRect(r, &fillRect))
		{
			PSrectfill(NX_X(&fillRect), NX_Y(&fillRect),
					NX_WIDTH(&fillRect), NX_HEIGHT(&fillRect));
		}
	}

	if ([[[NXApp graphicsMatrix]  findCellWithTag:TEXT]  state])
	{
		[font  set];
		NXSetRect(&testRect, 0, 0, 600, 250);
		if (NXIntersectsRect(r, &testRect))
		{
			PSmoveto(3, 50);
			PSshow("Adobe");
		}
	}
	
	/*
	*	Important - This method is important with this implementation
	*	of pattern emulation.
	*/
	[pattern unset];

	return self;
}

/*
*	Compare the bounds of the object with the rectangle to draw in order to
*	eliminate unnecessary drawing.
*/
- drawSelf:(NXRect *)r :(int) count
{
	int			ElapsedTime;

	if ([[NXApp  lockMatrix]  selectedTag] != LOCK_WINDOW)
		PSWSetPatternView();

	if (eraseFields)
		[self  eraseFields:self];

	PSsetgray(NX_WHITE);
	NXRectFill(r);
	NXRectClip(r);

	PSsetwindowtype(NX_RETAINED, [window  windowNum]);
	if (trace)
		DPSTraceContext(DPSGetCurrentContext(), YES);

	PSWMarkTime();  NXPing();
		[self  showGraphics:r];
	PSWReturnTime(&ElapsedTime);
	timing.time += ElapsedTime;
	timing.draws++;

	if (trace)
		DPSTraceContext(DPSGetCurrentContext(), NO);
	PSsetwindowtype(NX_BUFFERED, [window  windowNum]);

	return self;
}

@end
